package dao;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.List;

import com.mysql.cj.x.protobuf.MysqlxCrud.Insert;

//data access object
//功能类-数据访问类（数据层）
public class PersonDao {// insert delete update select
/**
 	需要知道每一个方法的作用以及传入的对象中需要包含哪些数据
 	insert中包含的是传入的数据，
 	delete中包含的是删除的条件
 	update包含的是更新的新内容以及更新的条件
 	select中包含的是查询的条件
 * */
    /**
     * 执行insert-sql插入一条记录
     * 
     * @param model
     * @return
     * @throws SQLException 
     */
	public static void main(String[] args) throws SQLException {
		PersonModel mm = new PersonModel();
		mm.setAge(30);
		mm.setName("李总");
		mm.setBirthday("1999-01-09");
		mm.setGender("male");
		mm.setCode("1010");
		PersonDao dd = new PersonDao();
		PersonModel m1 = new PersonModel();
		m1.setCode("1010");
		dd.deleteByCode(m1);
		
	}
	//定义方法时有返回结果：为了通过结果知道此方法运行的情况如何
	//例如此方法返回的结果是1，就意味着对一条语句产生了影响
	//基本的返回值类型：int String Integer
	//高级的返回值类型：自定义的返回类型
	//注意封装的意义、组成部分：私有的属性变量，公有的属性方法，构造方法、其他方法
	//此方法中的过程就是JDBC的过程：工具类的设计
	//设计工具类需要考虑的方面：如果JDBCUtil不会被继承，设置为final
	
	public String insert(PersonModel model) throws SQLException {// add save
        String sql = "insert into person(code,name,age,gender,birthday)values(?,?,?,?,?)";		//创建插入语句的sql语句
        //使用创建好的JDBCUtil获得数据库的的链接对象
        Connection conn = null;
        PreparedStatement ps = null;															//防止sql注入
        try {//把可能发生异常的少量代码放在try里(这就是使用try的好处，所以可以把不会产生异常的语句放外面)
        	conn = JDBCUtil.getConnection();	
            ps = conn.prepareStatement(sql);		//把问号填充上对应的数据
            ps.setString(1, model.getCode());
            ps.setString(2, model.getName());
            ps.setInt(3, model.getAge());
            ps.setString(4, model.getGender());
            ps.setString(5, model.getBirthday());
            int res = ps.executeUpdate();			//execute的目的：把语句发送到数据库中
            return res + "";						//返回一个结果以便看到执行情况如何				
            			
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            JDBCUtil.close(conn, ps);
        }
        return null;
    }

    /**
     * 根据逻辑主键删除记录
     * 
     * @param model
     * @return
     * @throws SQLException 
     */
    public String deleteByCode(PersonModel model) throws SQLException {
        String sql = "delete from person where code = ?";
        Connection conn = JDBCUtil.getConnection();
        if (conn == null)
            return null;
        PreparedStatement ps = null;
        try {
            ps = conn.prepareStatement(sql);
            ps.setString(1, model.getCode());
            return ps.executeUpdate() + "";
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            JDBCUtil.close(conn, ps);
        }
        return null;
    }

    /**
     * 根据逻辑主键修改记录其他全部字段
     * 
     * @param model
     * @return
     * @throws SQLException 
     */
    //多条件查询的主体
    public String update(PersonModel model) throws SQLException {
        String sql = "update person set name=?,age=?,gender=?,birthday=? where code=?";
        Connection conn = JDBCUtil.getConnection();
        if (conn == null)
            return null;
        PreparedStatement ps = null;
        try {
            ps = conn.prepareStatement(sql);
            ps.setString(1, model.getName());
            ps.setInt(2, model.getAge());
            ps.setString(3, model.getGender());
            ps.setString(4, model.getBirthday());
            ps.setString(5, model.getCode());
            return ps.executeUpdate() + "";
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            JDBCUtil.close(conn, ps);
        }
        return null;
    }

    /**
     * 根据多个查询条件 - 执行查询sql，返回结果构成的实体类集合
     * @throws SQLException 
     * 
     */
    //多条件查询时，用于在创建sql语句时在末尾进行追加
    public List<PersonModel> selectList(PersonModel model) throws SQLException {
        StringBuffer sql = new StringBuffer("select code,name,age,gender,birthday from person ");
        List<Object> vals = appendWhere(sql, model);
        Connection conn = JDBCUtil.getConnection();
        if (conn == null)
            return null;
        PreparedStatement ps = null;
        ResultSet rs = null;
        List<PersonModel> list = new ArrayList<>();
        try {
            ps = conn.prepareStatement(sql.toString());
            for (int i = 0; i < vals.size(); i++)
                ps.setObject(i + 1, vals.get(i));
            rs = ps.executeQuery();
            PersonModel p = null;
            while (rs.next()) {// ORM
                p = new PersonModel();
                p.setCode(rs.getString("code"));
                p.setName(rs.getString("name"));
                p.setAge(rs.getInt("age"));
                p.setGender(rs.getString("gender"));
                p.setBirthday(rs.getString("birthday"));
                list.add(p);
            }
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            JDBCUtil.close(conn, ps, rs);
        }
        return list;
    }

    private List<Object> appendWhere(StringBuffer sql, PersonModel model) {//只在此文件中使用的东西定义为private
        sql.append(" where 1=1 ");
        List<Object> vals = new ArrayList<>();
        String code = model.getCode();
        if (code != null && !code.trim().isEmpty()) {
            sql.append(" and code = ? ");
            vals.add(code.trim());
        }
        String name = model.getName();
        if (name != null && !name.trim().isEmpty()) {
            sql.append(" and name = ? ");
            vals.add(name.trim());
        }
        Integer age = model.getAge();
        if (age != null) {
            sql.append(" and age = ? ");
            vals.add(age);
        }

        Timestamp begin = model.getEntryTimeBegin();
        Timestamp end = model.getEntryTimeBegin();
        if (begin != null && end != null) {
            sql.append(" and entry_time between ? and ? ");
            vals.add(begin);
            vals.add(end);
        }

        return vals;
    }

}